/*
 * BlackBox Chess, by Tyler Eastman
 */

package bbchess;

import FICS.SimpleFICSInterface;
import TelnetClient.TelnetInterface;
import chessengine.EngineInterface;
import bbchess.dialogs.NewGameDialog;
import bbchess.dialogs.CapturedPiecesDialog;
import bbchess.dialogs.HistoryDialog;
import bbchess.dialogs.AboutDialog;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import java.awt.*;
import bbchess.units.*;
import bbchess.util.ChessGlassPane;
import bbchess.util.ImageLoader;
import bbchess.util.SoundLoader;

/**
 *
 * @author Tyler
 */
public class MainGui extends javax.swing.JFrame {

    // declare variables
    public ChessGlassPane glassPane;
    private ChessBoard chessBoard;
    private AboutDialog aboutDialog;
    private NewGameDialog newGameDialog;
    public CapturedPiecesDialog capturedPiecesDialog;
    public EngineInterface engineInterface;
    public HistoryDialog historyDialog;
    public GameManager gameManager;
    private TelnetInterface telnetInterface;
    private Point center;

    /** creates new form MainGui */
    public MainGui() {

        // initialize components
        this.setTitle("BlackBox Chess");
        this.setIconImage(ImageLoader.getIconImage());
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        // init glasspane
        glassPane = new ChessGlassPane();
        setGlassPane(glassPane);
        glassPane.setVisible(true);
        
        // init components
        chessBoard = new ChessBoard(this);
        initComponents();
        
        // add chessBoard
        chessDesk.add(chessBoard);
        chessBoard.setLocation(28, 28);
        glassPane.setBoard(chessBoard);
        
        // initialize variables
        historyDialog = new HistoryDialog(this, false);
        chessBoard.setHistoryDialog(historyDialog);
        engineInterface = null;
        capturedPiecesDialog = new CapturedPiecesDialog(this, false);
        gameManager = new GameManager(chessBoard);
        chessBoard.setGameManager(gameManager);
        
        pack();

        // make visible
        setLocationRelativeTo(null);
        setVisible(true);

        newGameDialog = new NewGameDialog(this, false, gameManager);
        newGameDialog.setVisible(true);
    }

    public static void main(String[] args) {

        EventQueue.invokeLater(new Runnable() {
            public void run() {

                // set look and feel
                try {
                    UIManager.setLookAndFeel(
                            UIManager.getSystemLookAndFeelClassName());
                } catch (Exception e) {
                    e.printStackTrace();
                }

                // load resources
                SoundLoader.loadSounds();
                ImageLoader.loadImages();

                new MainGui();
            }
        });
    }

    @Override
    public void paint(Graphics g) {
        paintComponents(g);
        g.dispose();
    }

    @Override
    public void update(Graphics g) {
        paint(g);
    }

    /**
     * @return the chessBoard
     */
    public ChessBoard getChessBoard() {
        return chessBoard;
    }

    /**
     * Sets the center point of the window, needs to be called after location and size have
     * been determined.
     */
    private void setCenter() {
        center = new Point(((int) getLocation().getX() + ((int) getWidth()/2)), ((int) getLocation().getY() + ((int) getHeight()/2)));
    }

    /**
     * Returns the center point of the window. Can be called anytime after setCenter
     * @return
     */
    public Point getCenter() {
        setCenter();
        return center;
    }

    public StatusPanel getStatusPanel() {
        return (StatusPanel) statusPanel;
    }

    @Override
    protected void finalize() {

        try {
            engineInterface.stopEngine();
        } catch (Exception ex) {/*engine not there, don't worry about it*/}

        try {
            super.finalize();
        } catch (Throwable ex) {
            Logger.getLogger(MainGui.class.getName()).log(Level.SEVERE, null, ex);
        }
        dispose();
    }

    @Override
    public void dispose() {
        try {
            engineInterface.stopEngine();
        } catch (Exception ex) {/*engine not there, don't worry about it*/}

        try {
            if (telnetInterface.getFicsInterface() != null) {
                telnetInterface.getFicsInterface().dispose();
            }
        } catch (Exception ex) {  }
        
        super.dispose();
    }


    public void updateTurnStatus(String player) {
        StatusPanel statusPanel1 = (StatusPanel) statusPanel;
        statusPanel1.updateTurnStatus(player);
    }

    public void enableEngineMenuItem (boolean choice) {
        engineMenuItem.setEnabled(choice);
        engineMenuItem.setSelected(!choice);
    }

    public void setEnableNetworkViewMenuItem(boolean choice) {
        networkMenuItem.setEnabled(choice);
    }

    public class ChessDesk extends JPanel {

        @Override
        public void paintComponent(Graphics g) {
            // draw desk
            g.drawImage(ImageLoader.getDeskImage(), 0, 0, getWidth(), getHeight(), this);

            // set the borderMultiplier, should be a value between 10-40, where 10 is the largest 
            //border, and 40 is the smallest.
            int borderMultiplier = 25;

            // draw board
            int border = (chessBoard.getWidth()/borderMultiplier);
            g.drawImage(ImageLoader.getBorderImage(), chessBoard.getX() - (border/2), chessBoard.getY() - (border/2), (chessBoard.getWidth() + border), (chessBoard.getWidth() + border), this);

        }
    }

    public void setNetworkViewMenuItemSelected(Boolean selected) {
        networkMenuItem.setSelected(selected);
    }
    
    public void setHistoryMenuItemSelected(Boolean selected) {
        historyMenuItem.setSelected(selected);
    }
    
    public void setEngineMenuItemSelected(Boolean selected) {
        engineMenuItem.setSelected(selected);
    }

    public void setStatusMenuItemSelected(Boolean selected) {
        capturedPiecesMenuItem.setSelected(selected);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel3 = new javax.swing.JPanel();
        statusPanel = new bbchess.StatusPanel();
        chessDesk = new ChessDesk();
        menuBar = new javax.swing.JMenuBar();
        gameMenu = new javax.swing.JMenu();
        newGameMenuItem = new javax.swing.JMenuItem();
        openGameMenuItem = new javax.swing.JMenuItem();
        saveGameMenuItem = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        exitMenuItem = new javax.swing.JMenuItem();
        settingsMenu = new javax.swing.JMenu();
        jMenuItem2 = new javax.swing.JMenuItem();
        jMenuItem3 = new javax.swing.JMenuItem();
        jMenuItem1 = new javax.swing.JMenuItem();
        jSeparator3 = new javax.swing.JPopupMenu.Separator();
        windowMenu = new javax.swing.JMenu();
        capturedPiecesMenuItem = new javax.swing.JCheckBoxMenuItem();
        historyMenuItem = new javax.swing.JCheckBoxMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        networkMenuItem = new javax.swing.JCheckBoxMenuItem();
        engineMenuItem = new javax.swing.JCheckBoxMenuItem();
        jMenu1 = new javax.swing.JMenu();
        aboutMenuItem = new javax.swing.JMenuItem();

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 100, Short.MAX_VALUE)
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 100, Short.MAX_VALUE)
        );

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setMinimumSize(new java.awt.Dimension(480, 514));

        statusPanel.setBackground(new java.awt.Color(102, 102, 102));
        statusPanel.setPreferredSize(new java.awt.Dimension(480, 34));
        statusPanel.setLayout(null);
        getContentPane().add(statusPanel, java.awt.BorderLayout.SOUTH);

        chessDesk.setDoubleBuffered(true);
        chessDesk.setBackground(new java.awt.Color(153, 153, 153));
        chessDesk.setPreferredSize(new java.awt.Dimension(480, 480));
        chessDesk.setRequestFocusEnabled(false);
        chessDesk.addComponentListener(new java.awt.event.ComponentAdapter() {
            public void componentResized(java.awt.event.ComponentEvent evt) {
                chessDeskComponentResized(evt);
            }
        });
        chessDesk.setLayout(null);
        getContentPane().add(chessDesk, java.awt.BorderLayout.CENTER);

        gameMenu.setText("Game");

        newGameMenuItem.setText("New Game...");
        newGameMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newGameMenuItemActionPerformed(evt);
            }
        });
        gameMenu.add(newGameMenuItem);

        openGameMenuItem.setText("Open Game...");
        gameMenu.add(openGameMenuItem);

        saveGameMenuItem.setText("Save Game...");
        gameMenu.add(saveGameMenuItem);
        gameMenu.add(jSeparator2);

        exitMenuItem.setText("Exit");
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        gameMenu.add(exitMenuItem);

        menuBar.add(gameMenu);

        settingsMenu.setText("Settings");

        jMenuItem2.setText("Game Properties");
        jMenuItem2.setEnabled(false);
        settingsMenu.add(jMenuItem2);

        jMenuItem3.setText("Network Properties");
        jMenuItem3.setEnabled(false);
        settingsMenu.add(jMenuItem3);

        jMenuItem1.setText("Appearance");
        jMenuItem1.setEnabled(false);
        settingsMenu.add(jMenuItem1);
        settingsMenu.add(jSeparator3);

        menuBar.add(settingsMenu);

        windowMenu.setText("Window");
        windowMenu.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                windowMenuActionPerformed(evt);
            }
        });

        capturedPiecesMenuItem.setText("Captured Pieces");
        capturedPiecesMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                capturedPiecesMenuItemActionPerformed(evt);
            }
        });
        windowMenu.add(capturedPiecesMenuItem);

        historyMenuItem.setText("History");
        historyMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                historyMenuItemActionPerformed(evt);
            }
        });
        windowMenu.add(historyMenuItem);
        windowMenu.add(jSeparator1);

        networkMenuItem.setText("Network");
        networkMenuItem.setEnabled(false);
        networkMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                networkMenuItemActionPerformed(evt);
            }
        });
        windowMenu.add(networkMenuItem);

        engineMenuItem.setText("Engine");
        engineMenuItem.setEnabled(false);
        engineMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                engineMenuItemActionPerformed(evt);
            }
        });
        windowMenu.add(engineMenuItem);

        menuBar.add(windowMenu);

        jMenu1.setText("Help");

        aboutMenuItem.setText("About");
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                aboutMenuItemActionPerformed(evt);
            }
        });
        jMenu1.add(aboutMenuItem);

        menuBar.add(jMenu1);

        setJMenuBar(menuBar);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        this.dispose();
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void newGameMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newGameMenuItemActionPerformed
        // start new game
        newGameDialog.setVisible(true);
    }//GEN-LAST:event_newGameMenuItemActionPerformed

    private void networkMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_networkMenuItemActionPerformed
        // if state is checked
        if (networkMenuItem.isSelected()) {
            gameManager.getFicsInterface().setVisible(true);
            setNetworkViewMenuItemSelected(true);
        }

        // else
        else {
            gameManager.getFicsInterface().setVisible(false);
            setNetworkViewMenuItemSelected(false);
        }
    }//GEN-LAST:event_networkMenuItemActionPerformed

    private void historyMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_historyMenuItemActionPerformed
        // if state is checked
        if (historyMenuItem.isSelected()) {
            historyDialog.setVisible(true);
        }

        // else
        else {
            historyDialog.setVisible(false);
        }
    }//GEN-LAST:event_historyMenuItemActionPerformed

    private void engineMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_engineMenuItemActionPerformed
        // if state is checked
        if (engineMenuItem.isSelected()) {
            engineInterface.setVisible(true);
        }

        // else
        else {
            engineInterface.setVisible(false);
        }
    }//GEN-LAST:event_engineMenuItemActionPerformed

    private void windowMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_windowMenuActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_windowMenuActionPerformed

    private void aboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_aboutMenuItemActionPerformed
        // if aboutDialog hasn't been initialized yet, do it.
        if (aboutDialog == null) {
            aboutDialog = new AboutDialog(this, false);
        }

        aboutDialog.setVisible(true);
    }//GEN-LAST:event_aboutMenuItemActionPerformed

    private void capturedPiecesMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_capturedPiecesMenuItemActionPerformed
        // if state is checked
        if (capturedPiecesMenuItem.isSelected()) {
            capturedPiecesDialog.setVisible(true);
        }

        // else
        else {
            capturedPiecesDialog.setVisible(false);
        }
    }//GEN-LAST:event_capturedPiecesMenuItemActionPerformed

    private void chessDeskComponentResized(java.awt.event.ComponentEvent evt) {//GEN-FIRST:event_chessDeskComponentResized
        
        // resize and reposition the chessboard when screen is resized
        int size = getHeight() - 150;
        int unit = size/8;

        // set chessboard to appropriate size (divisible by 8)
        chessBoard.setSize(unit*8, unit*8);

        // resize bottom panel
        bbchess.StatusPanel spanel = (bbchess.StatusPanel) statusPanel;
        spanel.resizePanel(getWidth());

        // set chessboard location
        chessBoard.setLocation((getWidth()/2) - (chessBoard.getWidth()/2), (int) chessBoard.getLocation().getY());
        chessBoard.validate();
        
        repaint();
    }//GEN-LAST:event_chessDeskComponentResized

    public TelnetInterface getTelnetInterface(String user, String pass) {
        if (telnetInterface == null) {
            //FICSInterface ficsInterface = new FICSInterface(this);
            SimpleFICSInterface ficsInterface = new SimpleFICSInterface(this);
            telnetInterface = new TelnetInterface(this, false, user, pass);

            ficsInterface.setTelnetInterface(telnetInterface);
            telnetInterface.setFicsInterface(ficsInterface);
        }

        return telnetInterface;
    }

    /**
     * Called by FicsInterface::logout to make the network eligible for rejoin
     */
    public void clearTelnetInterface() {
        telnetInterface = null;
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenuItem aboutMenuItem;
    private javax.swing.JCheckBoxMenuItem capturedPiecesMenuItem;
    private javax.swing.JPanel chessDesk;
    private javax.swing.JCheckBoxMenuItem engineMenuItem;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu gameMenu;
    private javax.swing.JCheckBoxMenuItem historyMenuItem;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private javax.swing.JPopupMenu.Separator jSeparator3;
    public javax.swing.JMenuBar menuBar;
    private javax.swing.JCheckBoxMenuItem networkMenuItem;
    private javax.swing.JMenuItem newGameMenuItem;
    private javax.swing.JMenuItem openGameMenuItem;
    private javax.swing.JMenuItem saveGameMenuItem;
    private javax.swing.JMenu settingsMenu;
    public javax.swing.JPanel statusPanel;
    private javax.swing.JMenu windowMenu;
    // End of variables declaration//GEN-END:variables

}
